#ifndef _LEMON_H_
#define _LEMON_H_

#include <unordered_map>
#include "struct.h"
/* The state vector for the entire parser generator is recorded as
** follows.  (LEMON uses no global variables and makes little use of
** static variables.  Fields in the following structure can be thought
** of as begin global variables in the program.) */

struct StateKeyHash
{
  unsigned statehash(const ConfigList& a) const;
  size_t operator()(const ConfigList& a) const
  {return statehash(a);}
};

struct StateKeyEqual
{
  int statecmp(const ConfigList& a, const ConfigList& b) const;
  bool operator()(const ConfigList& a, const ConfigList& b) const
  {return statecmp(a, b)==0;}
};

class Lemon {
 public:
  Lemon();
  std::vector<State*> sorted_states;   /* Table of states sorted by state number */
  std::vector<Rule*> rules;       /* List of all rules */
  Rule *startRule;  /* First rule */
  int nxstate;             /* nstate with tail degenerate states removed */
  int nrule;               /* Number of rules */
  int nsymbol;             /* Number of terminal and nonterminal symbols */
  int nterminal;           /* Number of terminal symbols */
  std::vector<Symbol*> symbols; /* Sorted array of pointers to symbols */
  int errorcnt;            /* Number of errors */
  Symbol *errsym;   /* The error symbol */
  Symbol *wildcard; /* Token that matches anything */
  char *name;              /* Name of the generated parser */
  char *arg;               /* Declaration of the 3th argument to parser */
  char *tokentype;         /* Type of terminal symbols in the parser stack */
  char *vartype;           /* The default type of non-terminal symbols */
  char *start;             /* Name of the start symbol for the grammar */
  char *stacksize;         /* Size of the parser stack */
  char *include;           /* Code to put at the start of the C file */
  char *error;             /* Code to execute when an error is seen */
  char *overflow;          /* Code to execute on a stack overflow */
  char *failure;           /* Code to execute on parser failure */
  char *accept;            /* Code to execute when the parser excepts */
  char *extracode;         /* Code appended to the generated file */
  char *tokendest;         /* Code to execute to destroy token data */
  char *vardest;           /* Code for the default non-terminal destructor */
  char *filename;          /* Name of the input file */
  char *outname;           /* Name of the current output file */
  char *tokenprefix;       /* A prefix added to token names in the .h file */
  int nconflict;           /* Number of parsing conflicts */
  int nactiontab;          /* Number of entries in the yy_action[] table */
  int tablesize;           /* Total table size of all tables in bytes */
  int basisflag;           /* Print only basis configurations */
  int has_fallback;        /* True if any %fallback is seen in the grammar */
  int nolinenosflag;       /* True if #line statements should not be printed */
  char *argv0;             /* Name of the program */

  int AddState(State* data, const ConfigList& key);
  State* FindState(const ConfigList& key);
  void SortRules();
private:
  std::unordered_map<const ConfigList, int, StateKeyHash, StateKeyEqual> state_index_;
};

#endif // _LEMON_H_
